df['est_monthly_rev'] = df['price_clean'] * df['reviews_per_month'].fillna(0) * 2
df['revenue_tier'] = pd.qcut(df['est_monthly_rev'], q=[0, 0.4, 0.8, 1.0],
labels=['Bottom 40%', 'Middle 40%', 'Top 20%'])
top = df[df['revenue_tier'] == 'Top 20%']
bottom = df[df['revenue_tier'] == 'Bottom 40%']
metrics = ['Superhost %', 'Instant Book %', 'Avg Rating']
top_vals = [
(top['host_is_superhost'] == 't').mean() * 100,
(top['instant_bookable'] == 't').mean() * 100,
top['review_scores_rating'].mean()
]
bottom_vals = [
(bottom['host_is_superhost'] == 't').mean() * 100,
(bottom['instant_bookable'] == 't').mean() * 100,
bottom['review_scores_rating'].mean()
]
fig = make_subplots(rows=1, cols=3, subplot_titles=metrics)
colors = ['#00CC96', '#EF553B']
for i, (metric, t, b) in enumerate(zip(metrics, top_vals, bottom_vals)):
fig.add_trace(go.Bar(x=['Top 20%', 'Bottom 40%'], y=[t, b],
marker_color=colors, showlegend=False), row=1, col=i+1)
fig.update_layout(
title=dict(text='What Separates Winners from Losers?', font=dict(size=16)),
height=350,
margin=dict(t=80)
)
# Add annotations for the punchline
fig.add_annotation(x=0.17, y=-0.15, xref='paper', yref='paper',
text='<b>3x gap</b>', showarrow=False, font=dict(size=12, color='#00CC96'))
fig.add_annotation(x=0.5, y=-0.15, xref='paper', yref='paper',
text='<b>1.4x gap</b>', showarrow=False, font=dict(size=12, color='#00CC96'))
fig.add_annotation(x=0.83, y=-0.15, xref='paper', yref='paper',
text='<b>No gap</b>', showarrow=False, font=dict(size=12, color='#636EFA'))
fig.show()